package com.ulife.permission.module.action;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.citrus.service.form.Group;
import com.alibaba.citrus.turbine.Context;
import com.alibaba.citrus.turbine.Navigator;
import com.alibaba.citrus.turbine.dataresolver.FormGroup;
import com.alibaba.citrus.webx.WebxException;
import com.ulife.common.ErrorMessage;
import com.ulife.common.GroupUtils;
import com.ulife.common.Result;
import com.ulife.common.exception.ManagerException;
import com.ulife.permission.common.FunctionEnum;
import com.ulife.permission.common.TargetEnum;
import com.ulife.permission.dao.dataobject.FunctionDO;
import com.ulife.permission.dao.dataobject.RoleDO;
import com.ulife.permission.dao.dataobject.TargetDO;
import com.ulife.permission.exceptions.RoleEditException;
import com.ulife.permission.manager.FunctionManager;
import com.ulife.permission.manager.RoleManager;
import com.ulife.permission.manager.TargetManager;

public class RoleAction {

	private static final Logger log = LoggerFactory.getLogger(RoleAction.class);
	
	@Autowired
	private RoleManager roleManager;
	@Autowired
	private TargetManager targetManager;
	@Autowired
	private FunctionManager functionManager;
	@Autowired
	private HttpServletRequest request;
	
	public void doAddRole(@FormGroup("addrole") Group group, Context context, Navigator nav) throws WebxException {
		GroupUtils groupUtil = new GroupUtils(group);
		String roleName = groupUtil.getString("roleName");
		String note = groupUtil.getString("note");
		
		RoleDO role = new RoleDO();
		role.setRoleName(roleName);
		role.setNote(note);
		role.setStatus(0);
		
		try {
			Result<RoleDO> result = roleManager.addRole(role);
			if (result == null || !result.isSuccess() || null == result.getModule()) {
				context.put("error", "系统错误");
				return;
			}
		} catch (ManagerException e) {
			context.put("error", "系统错误");
			log.error("login error, role name = " + roleName, e);
		}
		
	}
	
	public void doDelRole(@FormGroup("delrole") Group group, Context context, Navigator nav) throws WebxException {
		GroupUtils groupUtil = new GroupUtils(group);
		long roleId = groupUtil.getLong("roleId");
		int status = groupUtil.getInt("status");
		try {
			if (status < 0 || status > 1) {
				context.put("error", "系统错误");
				return;
			}
			if (roleId >= 0) {
				Result<RoleDO> roleResult = roleManager.getRoleById(roleId);
				if (roleResult != null && roleResult.isSuccess() && roleResult.getModule() != null) {
					RoleDO role = roleResult.getModule();
					if (role.getStatus() != status) {
						role.setStatus(status);
						Result<Integer> result = roleManager.updateRole(role);
						if (result == null || !result.isSuccess()) {
							context.put("error", "系统错误");
							return;
						}
					}
				}
				else {
					context.put("error", "系统错误");
					return;
				}
			}
		}
		catch (Exception e) {
			context.put("error", "系统错误");
			log.error("del role error, role id = " + roleId, e);
		}
	}
	
	public void doUpdateRole(@FormGroup("updaterole") Group group, Context context, Navigator nav) throws WebxException {
		GroupUtils groupUtil = new GroupUtils(group);
		long roleId = groupUtil.getLong("roleId");
		
		try {
			if (roleId >= 0) {
				Result<RoleDO> roleResult = roleManager.getRoleById(roleId);
				if (roleResult != null && roleResult.isSuccess() && roleResult.getModule() != null) {
					RoleDO role = roleResult.getModule();
					setRole(role, groupUtil);
					Result<Integer> updateResult = roleManager.updateRole(role);
					if (updateResult == null || !updateResult.isSuccess()) {
						log.error("update role error, role id = " + roleId);
						context.put("error", "更新错误");
						return;
					}
				}
			}
			else {
				context.put("error", "系统错误");
				log.error("update role error, role id = " + roleId);
			}
		} catch (ManagerException e) {
			context.put("error", "系统错误");
			log.error("update role error, role id = " + roleId, e);
		}
	}
	
	private void setRole(RoleDO role, GroupUtils group) {
		String roleName = group.getString("roleName");
		String note = group.getString("note");
		
		if (StringUtils.isNotBlank(roleName)) {
			role.setRoleName(roleName);
		}
		if (StringUtils.isNotBlank(note)) {
			role.setNote(note);
		}
	}
	
	public void doEditRole(Context context, Navigator nav) throws WebxException {
		String roleIdStr = request.getParameter("roleId");
		String[] targets = request.getParameterValues("target");
		String[] functions = request.getParameterValues("function");
		String target = StringUtils.join(targets, ",");
		String function = StringUtils.join(functions, ",");
		if (StringUtils.isNotBlank(roleIdStr)) {
			try {
				long roleId = Long.parseLong(roleIdStr);
				Result<RoleDO> result = roleManager.getRoleById(roleId);
				if (result != null && result.isSuccess() && null != result.getModule()) {
					RoleDO role = result.getModule();
					//更新页面、功能表可访问角色id
					String targetOld = role.getTargetList();
					String functionOld = role.getFunctionList();
					dealWithTarget(targetOld, targets, role.getRoleId());
					dealWithFunction(functionOld, functions, role.getRoleId());
					
					//更新角色表
					role.setTargetList(target);
					String targetName = buildTargetName(targets);
					role.setTargetNameList(targetName);
					role.setFunctionList(function);
					String functionName = buildFunctionName(functions);
					role.setFunctionNameList(functionName);
					Result<Integer> roleResult = roleManager.updateRole(role);
					if (roleResult == null || !roleResult.isSuccess()) {
						context.put("msg", ErrorMessage.ROLE_EDIT_ERROR);
					}
					else {
						context.put("msg", "保存成功");
					}
				}
			} 
			catch (RoleEditException e ) {
				context.put("msg", ErrorMessage.ROLE_EDIT_ERROR);
				nav.forwardTo("error");
			}
			catch (ManagerException e) {
				context.put("msg", "系统错误");
				log.error("edit role error", e);
			}
		}
		else {
			context.put("msg", "更新角色信息错误");
		}
	}
	
	private String buildFunctionName(String[] functions) {
		String functionName = null;
		if (functions != null) {
			List<String> nl = new ArrayList<String>();
			for (String f : functions) {
				FunctionEnum fe = FunctionEnum.getFunction(f);
				String fn = fe.getFunctionName();
				nl.add(fn);
			}
			functionName = StringUtils.join(nl, ",");
		}
		return functionName;
	}

	private String buildTargetName(String[] targets) {
		String targetName = null;
		if (targets != null) {
			List<String> tl = new ArrayList<String>();
			for (String t : targets) {
				String tn = TargetEnum.getTargetName(t);
				tl.add(tn);
			}
			targetName = StringUtils.join(tl, ",");
		}
		return targetName;
	}

	/**
	 * 处理target的roleId
	 * @param oldTarget
	 * @param targets
	 * @param roleId
	 * @return
	 */
	private boolean dealWithTarget(String oldTarget, String[] targets, long roleId) {
		String[] oldTargets = StringUtils.split(oldTarget, ",");
		List<String> oldTargetList = buildList(oldTargets);
		List<String> targetList = buildList(targets);
		
		List<String> addTarget = new ArrayList<String>();
		List<String> subTarget = new ArrayList<String>();
		if (oldTargetList != null) {
			for (String oldTar : oldTargetList) {
				if (!targetList.contains(oldTar)) {
					subTarget.add(oldTar);
				}
			}
		}
		if (targetList != null) {
			for (String tar : targetList) {
				if (!oldTargetList.contains(tar)) {
					addTarget.add(tar);
				}
			}
		}
		dealAddTarget(addTarget, roleId);
		dealSubTarget(subTarget, roleId);
		
		return true;
	}
	
	/**
	 * 处理function的roleId
	 * @param oleFunction
	 * @param functions
	 * @param roleId
	 * @return
	 */
	private boolean dealWithFunction(String oleFunction, String[] functions, long roleId) {
		String[] oleFunctions = StringUtils.split(oleFunction, ",");
		List<String> oldFunctionList = buildList(oleFunctions);
		List<String> functionList = buildList(functions);
		
		List<String> addFunction = new ArrayList<String>();
		List<String> subFunction = new ArrayList<String>();
		if (oldFunctionList != null) {
			for (String oldFunction : oldFunctionList) {
				if (!functionList.contains(oldFunction)) {
					subFunction.add(oldFunction);
				}
			}
		}
		if (functionList != null) {
			for (String function : functionList) {
				if (!oldFunctionList.contains(function)) {
					addFunction.add(function);
				}
			}
		}
		dealAddFunction(addFunction, roleId);
		dealSubFunction(subFunction, roleId);
		
		return true;
	}
	
	/**
	 * function减少roleId
	 * @param subFunction
	 * @param roleId
	 */
	private void dealSubFunction(List<String> subFunction, long roleId) {
		if (CollectionUtils.isNotEmpty(subFunction)) {
			for (String function : subFunction) {
				Result<FunctionDO> queryResult;
				try {
					queryResult = functionManager.getFunctionByFunctionId(function);
					if (queryResult != null && queryResult.isSuccess() && queryResult.getModule() != null) {
						FunctionDO functionDO = queryResult.getModule();
						String roleIdStr = functionDO.getRoleList();
						String[] roleIds;
						if (roleIdStr != null) {
							roleIds = StringUtils.split(roleIdStr, ",");
							List<String> idList = new ArrayList<String>();
							CollectionUtils.addAll(idList, roleIds);
							if (idList.contains(roleId + "")) {
								idList.remove(roleId + "");
								roleIdStr = StringUtils.join(idList, ",");
								functionDO.setRoleList(roleIdStr);
								Result<Integer> result = functionManager.updateFunction(functionDO);
								if (result == null || !result.isSuccess()) {
									throw new RoleEditException("function sub role id error, role id = " + roleId + ", function = " + function);
								}
							}
						}
					}
				} catch (ManagerException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * function增加roleId
	 * @param addFunction
	 * @param roleId
	 */
	private void dealAddFunction(List<String> addFunction, long roleId) {
		if (CollectionUtils.isNotEmpty(addFunction)) {
			for (String function : addFunction) {
				try {
					Result<FunctionDO> queryResult = functionManager.getFunctionByFunctionId(function);
					if (queryResult != null && queryResult.isSuccess() && queryResult.getModule() != null) {
						FunctionDO functionDO = queryResult.getModule();
						String roleIdStr = functionDO.getRoleList();
						String[] roleIds;
						if (roleIdStr != null) {
							roleIds = StringUtils.split(roleIdStr, ",");
							List<String> idList = new ArrayList<String>();
							CollectionUtils.addAll(idList, roleIds);
							if (!idList.contains(roleId + "")) {
								idList.add(roleId + "");
								roleIdStr = StringUtils.join(idList, ",");
								functionDO.setRoleList(roleIdStr);
								Result<Integer> result = functionManager.updateFunction(functionDO);
								if (result == null || !result.isSuccess()) {
									throw new RoleEditException("function add role id error, role id = " + roleId + ", function = " + function);
								}
							}
						}
					}
					else {
						FunctionDO functionDO = new FunctionDO();
						functionDO.setRoleList(roleId + "");
						functionDO.setStatus(0);
						functionDO.setFunctionId(function);
						Result<Integer> insertResult = functionManager.addFunction(functionDO);
						if (insertResult == null || !insertResult.isSuccess()) {
							throw new RoleEditException("intsert function error, function = " + function);
						}
						
					}
				} catch (ManagerException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * target减少roleId
	 */
	private void dealSubTarget(List<String> subTarget, long roleId) {
		if (CollectionUtils.isNotEmpty(subTarget)) {
			for (String target : subTarget) {
				Result<TargetDO> queryResult;
				try {
					queryResult = targetManager.getTargetByTargetId(target);
					if (queryResult != null && queryResult.isSuccess() && queryResult.getModule() != null) {
						TargetDO targetDO = queryResult.getModule();
						String roleIdStr = targetDO.getRoleList();
						String[] roleIds;
						if (roleIdStr != null) {
							roleIds = StringUtils.split(roleIdStr, ",");
							List<String> idList = new ArrayList<String>();
							CollectionUtils.addAll(idList, roleIds);
							if (idList.contains(roleId + "")) {
								idList.remove(roleId + "");
								roleIdStr = StringUtils.join(idList, ",");
								targetDO.setRoleList(roleIdStr);
								Result<Integer> result = targetManager.updateTarget(targetDO);
								if (result == null || !result.isSuccess()) {
									throw new RoleEditException("target sub role id error, role id = " + roleId + ", target = " + target);
								}
							}
						}
					}
				} catch (ManagerException e) {
					throw new RoleEditException(e);
				}
			}
		}
	}

	/**
	 * target增加roleId
	 */
	private void dealAddTarget(List<String> addTarget, long roleId) {
		if (CollectionUtils.isNotEmpty(addTarget)) {
			for (String target : addTarget) {
				try {
					Result<TargetDO> queryResult = targetManager.getTargetByTargetId(target);
					if (queryResult != null && queryResult.isSuccess() && queryResult.getModule() != null) {
						TargetDO targetDO = queryResult.getModule();
						String roleIdStr = targetDO.getRoleList();
						String[] roleIds;
						if (roleIdStr != null) {
							roleIds = StringUtils.split(roleIdStr, ",");
							List<String> idList = new ArrayList<String>();
							CollectionUtils.addAll(idList, roleIds);
							if (!idList.contains(roleId + "")) {
								idList.add(roleId + "");
								roleIdStr = StringUtils.join(idList, ",");
								targetDO.setRoleList(roleIdStr);
								Result<Integer> result = targetManager.updateTarget(targetDO);
								if (result == null || !result.isSuccess()) {
									throw new RoleEditException("target add role id error, role id = " + roleId + ", target = " + target);
								}
							}
						}
					}
					else {
						TargetDO targetDO = new TargetDO();
						targetDO.setRoleList(roleId + "");
						targetDO.setStatus(0);
						targetDO.setTargetId(target);
						Result<Integer> insertResult = targetManager.addTarget(targetDO);
						if (insertResult == null || !insertResult.isSuccess()) {
							throw new RoleEditException("insert target error, target = " + target);
						}
					}
				} catch (ManagerException e) {
					throw new RoleEditException(e);
				}
			}
		}
	}

	private List<String> buildList(String[] strings) {
		List<String> list = new ArrayList<String>();
		if (strings == null) {
			return list;
		}
		CollectionUtils.addAll(list, strings);
		return list;
	}
	
}
